package com.qcby.javabingfa.实现阻塞队列;

public class BlockingQueue {
    //声明对象公用锁
    private Object lock = new Object();
    //String类型的数组，存储队列元素
    private String[] strs = null;
    //队首指针
    private int head = 0;
    //队尾指针
    private int tail = 0;
    //存储的元素个数
    private int size = 0;

    //构造方法，用于构建定长数组，数组长度由参数指定
    public BlockingQueue(int capacity) {
        strs = new String[capacity];
    }

    public void put(String str) throws InterruptedException{
        synchronized(lock) {
            //队列已满发生阻塞
            while (size==str.length()){
                System.out.println("*******************队列已满,入队阻塞");
                lock.wait();
            }
            //入队列
            strs[tail]=str;
            tail++;

            if(tail >= strs.length) {
                tail = 0;
            }
            //存入后元素总数加一
            size++;
            //队列为空，出队发生操作阻塞时，入队后为其解除阻塞
            lock.notify();
        }
    }

    public String take() throws InterruptedException {
        //用于存储取出的元素，默认为null
        String str = null;
        synchronized (lock) {
            //队列为空时出队阻塞
            while (size == 0) {
                System.out.println("#################队列为空,出队阻塞");
                lock.wait();
            }
            //出队
            str = strs[head];
            head++;

            //实现环形队列的关键，超过数组长度后回归数组首位
            if(head == strs.length) {
                //回归数组首位
                head = 0;
            }
            //存入后元素总数加一
            size--;
            //队列已满，入队阻塞时，出队后为其解除阻塞
            lock.notify();
        }
        //返回取出的元素
        return str;
    }


        public static void main(String[] args) {
        // 创建一个容量为5的阻塞队列
        BlockingQueue queue = new BlockingQueue(5);

        // 生产者线程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 200; i++) {
                    String item = "Item" + i;
                    queue.put(item);
                    System.out.println("入队线程: " + item);
                    Thread.sleep((long) (Math.random() * 100)); // 模拟耗时操作
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Producer interrupted");
            }
        });

        // 消费者线程
        Thread consumer = new Thread(() -> {
            try {
                for (int i = 0; i < 200; i++) {
                    String item = queue.take();
                    System.out.println("出队线程: " + item);
                    Thread.sleep((long) (Math.random() * 100)); // 模拟耗时操作
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("Consumer interrupted");
            }
        });

        // 启动线程
        producer.start();
        consumer.start();

        // 等待线程结束
        try {
            producer.join();
            consumer.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
